package com.xzp.gkrpc.server;

import com.xzp.gkrpc.Request;
import com.xzp.gkrpc.Response;
import com.xzp.gkrpc.codec.Decoder;
import com.xzp.gkrpc.codec.Encoder;
import com.xzp.gkrpc.common.utils.ReflectionUtils;
import com.xzp.gkrpc.transprot.RequestHandler;
import com.xzp.gkrpc.transprot.TransportServer;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;

@Slf4j
@Data
public class RpcServer {
    private RpcServerConfig config;
    private TransportServer net;
    private Encoder encoder;
    private Decoder decoder;
    private ServiceManager serviceManager;
    private ServiceInvoker serviceInvoker;
    // requestHandler负责server端处理client request的逻辑。
    private RequestHandler requestHandler = new RequestHandler() {
        @Override
        public void onRequest(InputStream receive, OutputStream toResp) {
            Response response = new Response();
            try {
                // 从receive先读出request请求
                byte[] request_bytes = IOUtils.readFully(receive, receive.available());
                // 将request_bytes转为request
                Request request = decoder.decode(request_bytes, Request.class);
                log.info("get request {}", request);
                // 通过request去查找服务，instance包含调用对象与调用方法
                ServiceInstance instance = serviceManager.lookup(request);
                System.out.println("instance" + instance);
                // 通过ServiceInvoker调用服务
                Object result = serviceInvoker.invoke(instance, request);
                // 将服务调用的结果放到response对象中
                response.setData(result);
                // 0表示成功 1表示失败
                response.setCode(0);
            } catch (Exception e) {
                log.warn(e.getMessage(), e);
                response.setCode(1);
                response.setMessage("RPC got Error"
                        + e.getClass().getName() + ":" +
                        e.getMessage());
            } finally {
                // 将response对象转为bytes返回回去。
                try {
                    log.info("response client");
                    byte[] encode_bytes = encoder.encode(response);
                    toResp.write(encode_bytes);
                } catch (IOException e) {
                    log.warn(e.getMessage(), e);
                }
            }
        }
    };

    public RpcServer() {
        this.config = new RpcServerConfig();
        this.net = ReflectionUtils.newInstance(config.transportClass);
        this.net.init(config.getPort(), this.requestHandler);
        this.encoder = ReflectionUtils.newInstance(config.encoderClass);
        this.decoder = ReflectionUtils.newInstance(config.decoderClass);
        this.serviceInvoker = new ServiceInvoker();
        this.serviceManager= new ServiceManager();
    }

    /**
     * 把一个接口中的所有方法注册
     * @param interfaceClass
     * @param bean
     * @param <T>
     */
    public <T> void register(Class<T> interfaceClass, T bean){
        serviceManager.register(interfaceClass, bean);
    }

    public void start(){
        this.net.start();
    }

    public void stop(){
        this.net.stop();
    }



    public RpcServer(RpcServerConfig config){
        this.config = config;
        this.net = ReflectionUtils.newInstance(config.transportClass);
        this.net.init(config.getPort(), this.requestHandler);
        this.encoder = ReflectionUtils.newInstance(config.encoderClass);
        this.decoder = ReflectionUtils.newInstance(config.decoderClass);
        this.serviceInvoker = new ServiceInvoker();
        this.serviceManager= new ServiceManager();
    }
}
